/*
 * Copyright (c) 2012 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.libermundi.theorcs.main.tapestry.components;

import java.util.UUID;

import org.apache.commons.validator.routines.EmailValidator;
import org.apache.tapestry5.Asset;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.alerts.AlertManager;
import org.apache.tapestry5.annotations.Component;
import org.apache.tapestry5.annotations.OnEvent;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.annotations.SetupRender;
import org.apache.tapestry5.corelib.components.Form;
import org.apache.tapestry5.ioc.Messages;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.services.Request;
import org.apache.tapestry5.upload.services.UploadedFile;
import org.libermundi.theorcs.core.tapestry.mixins.RealTimeValidation;
import org.libermundi.theorcs.core.tapestry.model.RealTimeValidationResponse;
import org.libermundi.theorcs.core.tapestry.model.RealTimeValidationResponse.LEVEL;
import org.libermundi.theorcs.core.tapestry.services.assets.FileManager;
import org.libermundi.theorcs.core.tapestry.services.assets.FileType;
import org.libermundi.theorcs.core.tapestry.services.assets.FileValidator;
import org.libermundi.theorcs.core.tapestry.services.assets.OfsFilesUtils;
import org.libermundi.theorcs.core.tapestry.services.assets.OrcsFileSystem;
import org.libermundi.theorcs.security.model.User;
import org.libermundi.theorcs.security.services.SecurityManager;
import org.libermundi.theorcs.security.services.UserManager;
import org.libermundi.theorcs.security.tapestry.services.UserServices;

import com.google.common.base.Strings;

/**
 * @author Martin Papy
 *
 */
public class EditProfile {
	@Inject
	private SecurityManager _securityManager;
	
	@Inject
	private UserManager _userManager;
	
	@Inject
	private UserServices _userServices;
	
	@Inject
	private AlertManager _alertManager;
	
	@Inject
	private Messages _messages;
	
	@Inject
	private FileValidator _validator;
	
    @Inject
    private ComponentResources _resources;
    
    @Inject
    private Request _request;
    
    @Inject
    @Symbol(SymbolConstants.ASSET_PATH_PREFIX)
    private String _t5AssetPrefix;
    
    @Inject
    @OrcsFileSystem
    private FileManager _fileManager;
	
	@Component
	private Form _editProfileForm;
	
	/*------------- Fields for editProfileForm -------------*/
	@Property(write=false)
	private String _username; 

	@Property
	private String _email; 

	@Property
	private String _firstname; 

	@Property
	private String _lastname;
	
	@Property
	private String _nickname;
	
	@Property
	private String _newPassword;
	
	@Property
	private String _newPasswordConfirm;
	
	@Property
	private String _description;
	
	@Property
	private UploadedFile _avatar;
	
	@Property
	private boolean _deleteAvatar;
	
	/*------------- Render Phases -------------*/
	@SetupRender
	public void setupRender(){
		User currentUser = _securityManager.getCurrentUser();
		_username = currentUser.getUsername();
		_email = currentUser.getEmail();
		_firstname = currentUser.getFirstName();
		_lastname = currentUser.getLastName();
		_nickname = currentUser.getNickName();
		_description = currentUser.getDescription();
	}
	
	/*------------- Form Events -------------*/
	
	@OnEvent(value="validate",component="editProfileForm")
	public void validate(){
		User currentUser = _securityManager.getCurrentUser();
		
		// Check if Nickname already exists (even if deleted)
		if(!currentUser.getNickName().equalsIgnoreCase(_nickname) && !_userManager.isNickNameAvailable(_nickname)) {
			_editProfileForm.recordError(_messages.get("main.profile.edit.error.nicknameexists"));
		}
		
		if(!Strings.isNullOrEmpty(_newPassword) && !Strings.isNullOrEmpty(_newPasswordConfirm) && !_newPassword.equals(_newPasswordConfirm)){
			_editProfileForm.recordError(_messages.get("main.profile.edit.error.passwordnomatch"));
		}
		
		if((_avatar != null) && !_validator.isAllowed(_avatar.getFileName(), FileType.IMAGE)){
			_editProfileForm.recordError(_messages.get("main.profile.edit.error.filenotallowed"));
		}
	}	
	
	@OnEvent(value="success",component="editProfileForm")
	public void success(){
		User currentUser = _securityManager.getCurrentUser();
		currentUser.setFirstName(_firstname);
		currentUser.setLastName(_lastname);
		currentUser.setNickName(_nickname);
		
		if(!Strings.isNullOrEmpty(_newPassword) && !Strings.isNullOrEmpty(_newPasswordConfirm)) {
			currentUser.setPassword(_newPassword);
		}
		
		if(!currentUser.getEmail().equalsIgnoreCase(_email)){
			currentUser.setEmail(_email);
			currentUser.setActivationKey(UUID.randomUUID().toString());
			currentUser.setActive(Boolean.FALSE); // Set to TRUE once clicked in Activation Email
			_userServices.sendActivationEmail(currentUser);
		}
		
		if(_avatar != null){
			_deleteAvatar = Boolean.TRUE;
		}
		
		if(_deleteAvatar){
			if(!Strings.isNullOrEmpty(currentUser.getAvatar())) {
				_fileManager.delete(OfsFilesUtils.stripPrefix(currentUser.getAvatar()));
			}
			currentUser.setAvatar(null);
		}
		
		if(_avatar != null){
			Asset savedAvatar = _fileManager.save(_avatar,FileType.IMAGE);
			currentUser.setAvatar(OfsFilesUtils.getPrefixedPathFromUrl(savedAvatar.toClientURL(), _request, _t5AssetPrefix));
		}
		
		currentUser.setDescription(_description);
		
		_userManager.save(currentUser);

		// At this point we should send an Activation Email to the User
		_alertManager.success(_messages.get("main.profile.edit.success"));

		_resources.triggerEvent("switchMode", null, null);
	}
		
	/*------------- Real Time Validation Events -------------*/
	
	@OnEvent(value=RealTimeValidation.EVENT_NAME,component="nickname")
	public RealTimeValidationResponse validateNickName(String nickname){
		if(nickname.equalsIgnoreCase(_securityManager.getCurrentUser().getNickName())) {
			return new RealTimeValidationResponse(LEVEL.SUCCESS,"");
		}
		
		boolean usernameAvailable = _userManager.isNickNameAvailable(nickname);
		String message = "";
		LEVEL success = LEVEL.SUCCESS;

		if(!usernameAvailable) {
			success = LEVEL.FAILED;
			message = _messages.get("main.profile.edit.error.nicknameexists");
		}

		return new RealTimeValidationResponse(success,message);
	}
	
	@OnEvent(value=RealTimeValidation.EVENT_NAME,component="email")
	public RealTimeValidationResponse validateEmail(String email){
		String message = "";
		LEVEL success = LEVEL.SUCCESS;
		
		EmailValidator v = EmailValidator.getInstance();		
		
		if(!v.isValid(email)) {
			success = LEVEL.FAILED;
			message = _messages.get("main.profile.edit.error.invalidemail");
		} else if(!email.equalsIgnoreCase(_securityManager.getCurrentUser().getEmail())){
			success = LEVEL.WARNING;
			message = _messages.get("main.profile.edit.warning.emailchanged");
		}
		
		return new RealTimeValidationResponse(success,message);
	}	
}
